﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

using Seven.Core.IRepositories;
using Seven.EntityBasic;
using Seven.MsSql.Context;
using Seven.Tools.Helper;

namespace Seven.MsSql
{
    /// <summary>
    /// 工作单元
    /// </summary
    public partial class MsSqlUnitOfWork
    {
        /// <summary>
        /// 数据对象
        /// </summary>
        private DbContext dbContext { get; set; }

        /// <summary>
        /// 是否已经提交
        /// </summary>
        private bool isCommitted { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public MsSqlUnitOfWork()
        {
            dbContext = new EFDbContext();
        }

        /// <summary>
        /// 仓储缓存
        /// </summary>
        private Dictionary<Type, object> repositoryCache = new Dictionary<Type, object>();

        /// <summary>
        /// 获取仓储
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <typeparam name="TKey">TEntity实体的主键类型</typeparam>
        /// <typeparam name="R">仓储接口</typeparam>
        /// <returns>仓储实例</returns>
        private R GetRepositoryByInstance<TEntity, TKey, R>()
            where TKey : struct
            where TEntity : EntityBase<TKey>
            where R : class, IBaseRepository<TEntity, TKey>, new()
        {
            if (!repositoryCache.ContainsKey(typeof(TEntity)))
            {
                var repository = new R();

                repository.SetContext(dbContext);

                repositoryCache.Add(typeof(TEntity), repository);

                return repository;
            }
            else { return (R)repositoryCache[typeof(TEntity)]; }
        }

        /// <summary>
        /// 获取仓储
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <typeparam name="TKey">TEntity实体的主键类型</typeparam>
        /// <typeparam name="R">仓储接口</typeparam>
        /// <returns>仓储实例</returns>
        public R GetRepository<TEntity, TKey, R>()
            where TKey : struct
            where TEntity : EntityBase<TKey>
            where R : class, IBaseRepository<TEntity, TKey>
        {
            string entityName = typeof(TEntity).Name;

            return GetType().GetProperty(entityName).GetValue(this, null) as R;
        }

        /// <summary>
        /// 开始数据事务
        /// </summary>
        public void BeginTransaction()
        {
            isCommitted = false;
        }

        /// <summary>
        /// 提交工作单元
        /// </summary>
        /// <returns>受影响行数</returns>
        public int Commit()
        {
            if (!isCommitted)
            {
                isCommitted = true;
                if (dbContext.ChangeTracker.HasChanges())
                {
                    try { return dbContext.SaveChanges(); }
                    catch (Exception e)
                    {
                        throw ExceptionHelper.ThrowDataAccessException(e.Message);
                    }
                }
                else { return 0; }
            }
            else { return 0; }
        }

        /// <summary>
        /// 执行回滚事务
        /// </summary>
        public void Rollback()
        {
            // Entity Framework 不需要此项
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (!isCommitted) { Commit(); }
            if (dbContext != null) { try { dbContext.Dispose(); dbContext = null; } catch { } }
        }
    }
}
